﻿using System;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;
using NazTek.Core;

namespace NazTek.Repository
{

    /// <summary>
    /// Captures database context and logging delegate.
    /// </summary>
    public interface IRepositoryBase : IDisposable
    {
        /// <summary>
        /// Gets/sets database context.
        /// </summary>
        IDbContext DbContext { get; set; }
        /// <summary>
        /// Gets/sets logging delegate.
        /// </summary>
        Action<string> Log { get; set; }
    }
    /// <summary>
    /// Encapsulates generic access API to database objects.
    /// </summary>
    /// <typeparam name="T">Database object type.</typeparam>
    public interface IRepository<T> : IRepositoryBase where T : class, IEntity
    {
        /// <summary>
        /// Gets the expression to fetch all available records of the underlying type.
        /// </summary>
        /// <returns>The expression to fetch all available records.</returns>
        IQueryable<T> GetAll();
        /// <summary>
        /// Executes dynamic SQL.
        /// </summary>
        /// <param name="query">The query string to execute.</param>
        /// <returns>Typed query result.</returns>
        DbRawSqlQuery<T> ExecuteQuery(string query);
        /// <summary>
        /// Gets all available records of the underlying type.
        /// </summary>
        /// <returns>All available records.</returns>
        List<T> GetAllList();
        /// <summary>
        /// Insert a record of the specified type.
        /// </summary>
        /// <param name="entity">The record to insert.</param>
        /// <returns>Number of state entries written to the database.</returns>
        int Insert(T entity);
        /// <summary>
        /// Deletes a database record.
        /// </summary>
        /// <param name="entity">The record to delete.</param>
        /// <returns>Number of state entries written to the database.</returns>
        int Delete(T entity);
        /// <summary>
        /// Update a database record.
        /// </summary>
        /// <param name="entity">The record to update.</param>
        /// <returns>Number of state entries written to the database.</returns>
        int Update(T entity);
        /// <summary>
        /// Update database records.
        /// </summary>
        /// <param name="entities">The records to update.</param>
        /// <returns>Number of state entries written to the database.</returns>
        int Update(List<T> entities);
        /// <summary>
        /// Finds database record with matching id.
        /// </summary>
        /// <param name="id">Primary key to find in database table.</param>
        /// <returns>Database table record with matching primary key id.</returns>
        T FindById(string id);
    }
    /// <summary>
    /// Encapsulates generic access API to database objects asynchronously.
    /// </summary>
    /// <typeparam name="T">Database object type.</typeparam>
    public interface IRepositoryAsync<T> : IRepositoryBase where T : class, IEntity
    {
        /// <summary>
        /// Gets the expression to fetch all available records of the underlying type.
        /// </summary>
        /// <returns>The expression to fetch all available records.</returns>
        Task<IQueryable<T>> GetAllAsync();
        /// <summary>
        /// Executes dynamic SQL.
        /// </summary>
        /// <param name="query">The query string to execute.</param>
        /// <returns>Typed query result.</returns>
        Task<DbRawSqlQuery<T>> ExecuteQueryAsync(string query);
        /// <summary>
        /// Gets all available records of the underlying type.
        /// </summary>
        /// <returns>All available records.</returns>
        Task<List<T>> GetAllListAsync();
        /// <summary>
        /// Insert a record of the specified type.
        /// </summary>
        /// <param name="entity">The record to insert.</param>
        /// <returns>Number of state entries written to the database.</returns>
        Task<int> InsertAsync(T entity);
        /// <summary>
        /// Deletes a database record.
        /// </summary>
        /// <param name="entity">The record to delete.</param>
        /// <returns>Number of state entries written to the database.</returns>
        Task<int> DeleteAsync(T entity);
        /// <summary>
        /// Update a database record.
        /// </summary>
        /// <param name="entity">The record to update.</param>
        /// <returns>Number of state entries written to the database.</returns>
        Task<int> UpdateAsync(T entity);
        /// <summary>
        /// Update database records.
        /// </summary>
        /// <param name="entities">The records to update.</param>
        /// <returns>Number of state entries written to the database.</returns>
        Task<int> UpdateAsync(List<T> entities);
        /// <summary>
        /// Finds database record with matching id.
        /// </summary>
        /// <param name="id">Primary key to find in database table.</param>
        /// <returns>Database table record with matching primary key id.</returns>
        Task<T> FindByIdAsync(string id);
    }
}